﻿#include "EditBox.h"

static const int s_x = 2;
static const int s_y = 1;
bool EditBox::init(const std::string &placeHolder, int limit, int fntSize)
{
	if (!DrawNode::init())
	{
		return false;
	}
	if (!NodeSnatch::init(this))
	{
		return false;
	}
	this->addChild(_labelPlaceHolder = Label2::create(placeHolder, fntSize));
	_labelPlaceHolder->setColor(Color3B::GRAY);
	this->addChild(_label = Label2::create("", fntSize));
	string _placeHolder = placeHolder;
	for (int i = placeHolder.size(); i < limit; ++i)
	{
		_placeHolder.push_back(' ');
	}
	_label->setString(_placeHolder);
	Size size = _label->getContentSize();
	this->setContentSize(size + Size(s_x * 2, s_y * 2 + 2));
	_label->setString("");
	_label->setPosition(s_x, s_y);
	_labelPlaceHolder->setPosition(s_x + 2, s_y);

	_layerCursor = LayerColor::create();
	_layerCursor->setContentSize(Size(3, size.height));
	_layerCursor->setColor(Color3B::WHITE);
	_layerCursor->setOpacity(0xff);
	this->addChild(_layerCursor);
	_layerCursor->setPosition(s_x, s_y);
	_layerCursor->setVisible(false);
	
	auto call = CallFuncN::create([](Node* n)
	{
		n->runAction(TintTo::create(0.5f, random(0, 0xff), random(0, 0xff), random(0, 0xff)));
	});
	_layerCursor->runAction(RepeatForever::create(Sequence::create(call, DelayTime::create(0.5f), nullptr)));
	_limit = limit;
	return true;
}


void EditBox::setContentSize(const Size& contentSize)
{
	DrawNode::setContentSize(contentSize);
	DrawNode::clear();
	DrawNode::drawRect(Vec2::ZERO, _contentSize, Color4F(_colorLine));
	_transformUpdated = true;
}


void EditBox::doClick(const Vec2& location, bool isActiveForListener)
{
	if (isActiveForListener)
	{
		EditBoxDelegate::getInstance()->setEditBox(this);
		DrawNode::clear();
		DrawNode::drawRect(Vec2::ZERO, _contentSize, Color4F(_colorLine = Color3B::WHITE));
		_transformUpdated = true;
		_layerCursor->setVisible(true);
	}
	else
	{
		EditBoxDelegate::getInstance()->setEditBox(nullptr);
		DrawNode::clear();
		DrawNode::drawRect(Vec2::ZERO, _contentSize, Color4F(_colorLine = Color3B::GRAY));
		_transformUpdated = true;
//		_layerCursor->stopAllActions();
		_layerCursor->setVisible(false);
	}
}

void EditBox::insertText(const char* text, size_t len)
{
	int count = 0;
	for (; count < len;)
	{
		if (text[count] & 0x80)
		{
			count += 2;
			if (_charCount + count > _limit)
			{
				count -= 2;
				break;
			}
		}
		else
		{
			++count;
			if (_charCount + count > _limit)
			{
				--count;
				break;
			}
		}
	}
// 	asert(count % 2 == 0, "insetText char count % 2 != 0");
// 	count = len - count / 2;
	_charCount += count;
	if (_charCount > 0)
	{
		_labelPlaceHolder->setVisible(false);
	}
	_label->setString(_label->getString() + string(text, count));
	_layerCursor->setPositionX(s_x + _label->getContentSize().width);
}

void EditBox::deleteBackward()
{
	string str = _label->getString();
	if (str.empty())
	{
		return;
	}
	if (str.back() & 0x80)
	{
		str.pop_back();
		str.pop_back();
		_charCount -= 2;
	}
	else
	{
		str.pop_back();
		--_charCount;
	}
	
	if (_charCount == 0)
	{
		_labelPlaceHolder->setVisible(true);
	}
	_label->setString(str);
	_layerCursor->setPositionX(s_x + _label->getContentSize().width);
}

void EditBox::controlKey(EventKeyboard::KeyCode keyCode)
{

}



static EditBoxDelegate* s_dditBoxDelegate = nullptr;
EditBoxDelegate* EditBoxDelegate::getInstance()
{
	if (!s_dditBoxDelegate)
	{
		s_dditBoxDelegate = new EditBoxDelegate();
	}
	return s_dditBoxDelegate;
}

void EditBoxDelegate::setEditBox(EditBox* editBox)
{
	_currEditBox = editBox;
	if (_currEditBox)
	{
		attachWithIME();
	}
	else
	{
		detachWithIME();
	}
}


void EditBoxDelegate::insertText(const char* text, size_t len)
{
	if (_currEditBox && _currEditBox->isEnabled() && _currEditBox->isVisible())
	{
		_currEditBox->insertText(text, len);
	}
}

void EditBoxDelegate::deleteBackward()
{
	if (_currEditBox && _currEditBox->isEnabled() && _currEditBox->isVisible())
	{
		_currEditBox->deleteBackward();
	}
}

void EditBoxDelegate::controlKey(EventKeyboard::KeyCode keyCode)
{
	if (_currEditBox && _currEditBox->isEnabled() && _currEditBox->isVisible())
	{
		_currEditBox->controlKey(keyCode);
	}
}
